import com.arcadedb.database.Database;
import com.arcadedb.database.DatabaseFactory;
import com.arcadedb.graph.MutableVertex;
import com.arcadedb.graph.Vertex;
import com.arcadedb.query.sql.executor.ResultSet;
import com.arcadedb.schema.Property;
import com.arcadedb.schema.Schema;
import com.arcadedb.schema.Type;
import com.arcadedb.schema.VertexType;
import indi.hjhk.exception.ExceptionSerializer;
import indi.hjhk.log.Logger;
import nju.hjh.arcadedb.timeseries.TimeseriesEngine;
import nju.hjh.arcadedb.timeseries.exception.TimeseriesException;
import nju.hjh.arcadedb.timeseries.statistics.DoubleStatistics;
import nju.hjh.arcadedb.timeseries.statistics.LongStatistics;

import java.util.ArrayList;
import java.util.Random;

public class CsvQueryTest {
    public static void singleObjQuery() {
        Logger logger = Logger.getPureLogger("CSV_Arcade");

        DatabaseFactory dbf = new DatabaseFactory("./databases/test");
        Database db;
        if (dbf.exists()){
            db = dbf.open();
        }else{
            db = dbf.create();
        }

        Random r = new Random();

        ArrayList<Long> startList = new ArrayList<>();
        ArrayList<Long> endList = new ArrayList<>();
        final int testCases = 20;
        final long timeSpan = 1000000;

        startList.add(0L);
        endList.add(timeSpan-1);
        for (int i=0; i<testCases; i++){
            long start = r.nextLong(timeSpan);
            startList.add(start);
            endList.add(r.nextLong(start, timeSpan));
        }

        Vertex test = ArcadeTSDBWorker.getVertexById(db, "test", "id", "test");
        if (test == null){
            logger.logOnStderr("target test:test not found");
            db.close();
            return;
        }

        TimeseriesEngine tsEngine = TimeseriesEngine.getInstance(db);

        tsEngine.begin();

        for (int i=0; i<startList.size(); i++){
            long startTime = System.currentTimeMillis();

            long start = startList.get(i);
            long end = endList.get(i);

            try {
                LongStatistics intStat = (LongStatistics) tsEngine.aggregativeQuery(test, "int", start, end);
                DoubleStatistics doubleStat = (DoubleStatistics) tsEngine.aggregativeQuery(test, "double", start, end);
                logger.logOnStdout("stats [%d, %d): avg(int)=%f ,avg(double)=%f", start, end+1, (double)intStat.sum/intStat.count, doubleStat.sum/doubleStat.count);
            }catch (TimeseriesException e){
                tsEngine.rollback();
                logger.logOnStderr(ExceptionSerializer.serializeAll(e));
                db.close();
                return;
            }

            long elapsed = System.currentTimeMillis() - startTime;
            logger.logOnStdout("time used: %dms", elapsed);
        }
        tsEngine.commit();

        db.close();

        // iotdb command
        for (int i=0; i<startList.size(); i++){
            logger.logOnStdout("select avg(int), avg(double) from root.test group by ([%d, %d), 100d)", startList.get(i), endList.get(i)+1);
        }
    }

    public static void multiObjQuery(){
        Logger logger = Logger.getPureLogger("CSV_Arcade");

        DatabaseFactory dbf = new DatabaseFactory("./databases/test");
        Database db;
        if (dbf.exists()){
            db = dbf.open();
        }else{
            db = dbf.create();
        }

        Random r = new Random();

        ArrayList<Integer> objList = new ArrayList<>();
        final int testCases = 20;
        final int objSize = 100000;
        final int timeSpan = 10;

        for (int i=0; i<testCases; i++){
            int obj = r.nextInt(objSize);
            objList.add(obj);
        }

        TimeseriesEngine tsEngine = TimeseriesEngine.getInstance(db);

        tsEngine.begin();

        for (int i=0; i<objList.size(); i++){
            long startTime = System.currentTimeMillis();

            Vertex vertex = ArcadeTSDBWorker.getVertexById(db, "test", "id", "obj"+objList.get(i));

            try {
                LongStatistics intStat = (LongStatistics) tsEngine.aggregativeQuery(vertex, "int", 0, timeSpan-1);
                DoubleStatistics doubleStat = (DoubleStatistics) tsEngine.aggregativeQuery(vertex, "double", 0, timeSpan-1);
                logger.logOnStdout("stats %s:[%d, %d): avg(int)=%f ,avg(double)=%f", "obj"+objList.get(i), 0, timeSpan, (double)intStat.sum/intStat.count, doubleStat.sum/doubleStat.count);
            }catch (TimeseriesException e){
                tsEngine.rollback();
                logger.logOnStderr(ExceptionSerializer.serializeAll(e));
                db.close();
                return;
            }

            long elapsed = System.currentTimeMillis() - startTime;
            logger.logOnStdout("time used: %dms", elapsed);
        }
        tsEngine.commit();

        db.close();

        // iotdb command
        for (int i=0; i<objList.size(); i++){
            logger.logOnStdout("select avg(int), avg(double) from root.test.%s group by ([%d, %d), 100d)", "obj"+objList.get(i), 0, timeSpan);
        }
    }

    public static void main(String[] args) {
        multiObjQuery();
    }
}
